package file

import (
	"ManageServer/conf"
	"ManageServer/defs/dbs"
	"ManageServer/lib"
	"ManageServer/utils/encryption"
	"ManageServer/utils/response"
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"image"
	"image/png"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
)

type Controller struct{}

// 注册路由
func (self Controller) RegisterRoute(r *gin.RouterGroup) {
	r.POST("/file/Upload", response.API(self.Upload))                                 // 后台 - 上传文件
	r.GET("/file/Download/:hash", lib.SetCacheControl(), response.API(self.Download)) // 下载文件,增加文件缓存
	r.GET("/file/GetUserTemplate", response.API(self.GetUserTemplate))                // 后台 - 下载文件
	r.GET("/file/DownloadImage/:hash", response.API(self.DownloadImage))              // 缩放图片

	//登录类接口不在角色权限内
	lib.SetRouteAuthorization(map[string]map[string][]string{
		"超级管理员": map[string][]string{
			"file": {"Upload", "Download", "GetUserTemplate", "DownloadImage"},
		},
		"管理员": map[string][]string{
			"file": {"Upload", "Download", "GetUserTemplate", "DownloadImage"},
		},
		"患陪": map[string][]string{
			"file": {"Upload", "Download", "GetUserTemplate", "DownloadImage"},
		},
		"职工": map[string][]string{
			"file": {"Upload", "Download", "GetUserTemplate", "DownloadImage"},
		},
		"第三方职工": map[string][]string{
			"file": {"Upload", "Download", "GetUserTemplate", "DownloadImage"},
		},
	})
}

func sha(header *multipart.FileHeader) (hash string, value []byte, err error) {
	multipart_file, err := header.Open()
	if err != nil {
		return
	}
	defer multipart_file.Close()
	value, err = ioutil.ReadAll(multipart_file)
	if err != nil {
		return
	}

	hash = encryption.Hash(value)
	return
}

/**
 * @api {post} /file/Upload Upload
 * @apiVersion 1.0.0
 * @apiGroup file
 * @apiDescription 上传附件
 *
 * @apiParam {FormData} attachment
 *
 * @apiSuccessExample {json} Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *          "code":"200",
 * 			"msg":""
 *			"data":{
 *				"hash":"11111111"
 *			}
 *      }
 *
 * @apiErrorExample {json} Error-Response:
 *     HTTP/1.1 404 Not Found
 *     {
 *			"code":"01001",
 * 			"msg":"无此操作权限"
 *			"data":{}
 *     }
 */
func (self Controller) Upload(c *gin.Context) (data map[string]interface{}, err error) {
	//保存文件流
	//check params
	header, err := c.FormFile("attachment")
	if err != nil {
		return
	}

	// 获取文件名称
	name := header.Filename
	// hash 文件内容获取摘要和文件流
	hash, value, err := sha(header)

	var file dbs.DbFile
	file.Hash = hash
	err = file.Exit()
	if err == nil {
		// hash存在，不重复保存文件
		data = map[string]interface{}{"hash": hash}
		return data, nil
	}
	if err != nil && err != gorm.ErrRecordNotFound {
		// 查询文件时错误
		return
	}

	// 文件未保存过
	file = dbs.DbFile{
		Hash:  hash,
		Name:  name,
		Value: value,
	}
	err = file.Create()
	if err != nil {
		return
	}

	data = map[string]interface{}{"hash": hash}
	return data, nil
}

/**
 * @api {get} /file/Download/:hash Download
 * @apiVersion 1.0.0
 * @apiGroup file
 * @apiDescription 下载附件
 *
 * @apiErrorExample {json} Error-Response:
 *     HTTP/1.1 404 Not Found
 *     {
 *			"code":"01001",
 * 			"msg":"无此操作权限"
 *			"data":{}
 *     }
 */
func (self Controller) Download(c *gin.Context) (data map[string]interface{}, err error) {
	// check params
	hash := c.Param("hash")

	var file dbs.DbFile
	// check null
	file.Hash = hash
	err = file.Get()
	if err != nil {
		return
	}

	c.Writer.WriteHeader(http.StatusOK)

	// 处理名称乱码问题
	_, err = url.ParseQuery(file.Name)

	c.Header("Content-Type", "application/octet-stream;charset=UTF-8")
	c.Header("Content-Disposition", "attachment; filename="+file.Name)
	c.Header("Accept-Length", fmt.Sprintf("%d", len(file.Value)))
	c.Writer.Write(file.Value)
	c.Abort()
	return
}

/**
 * @api {get} /file/DownloadImage/:hash?e=200*200 DownloadImage
 * @apiVersion 1.0.0
 * @apiGroup file
 * @apiDescription 下载图片
 *
 * @apiErrorExample {json} Error-Response:
 *     HTTP/1.1 404 Not Found
 *     {
 *			"code":"01001",
 * 			"msg":"无此操作权限"
 *			"data":{}
 *     }
 */
func (self Controller) DownloadImage(c *gin.Context) (data map[string]interface{}, err error) {
	// check params
	hash := c.Param("hash")

	var file dbs.DbFile
	// check null
	file.Hash = hash
	err = file.Get()
	if err != nil {
		return
	}

	var t_value []byte
	t_value = file.Value

	// 缩放比例
	e := c.Query("e")
	es := strings.Split(e, "*")
	if e != "" && len(es) > 1 {
		// 得到宽高
		w, _ := strconv.Atoi(es[0])
		h, _ := strconv.Atoi(es[1])

		// reset format of data []byte to image.Image
		// 原图 先转换为 image 格式
		original_image, _, _ := image.Decode(bytes.NewReader(file.Value))

		// 修改图片尺寸至 横 65
		thumbnail_image := imaging.Resize(original_image, w, h, imaging.Lanczos)

		// 缩略图取流 []byte
		var b bytes.Buffer
		png.Encode(&b, thumbnail_image)
		t_value = b.Bytes()
	}

	c.Writer.WriteHeader(http.StatusOK)

	// 处理名称乱码问题
	_, err = url.ParseQuery(file.Name)

	c.Header("Content-Type", "application/octet-stream;charset=UTF-8")
	c.Header("Content-Disposition", "attachment; filename="+file.Name)
	c.Header("Accept-Length", fmt.Sprintf("%d", len(t_value)))
	c.Writer.Write(t_value)
	c.Abort()
	return
}

/**
 * @api {get} /file/GetUserTemplate GetUserTemplate
 * @apiVersion 1.0.0
 * @apiGroup file
 * @apiDescription 获取用户导入模板
 *
 * @apiErrorExample {json} Error-Response:
 *     HTTP/1.1 404 Not Found
 *     {
 *			"code":"01001",
 * 			"msg":"无此操作权限"
 *			"data":{}
 *     }
 */
func (self Controller) GetUserTemplate(c *gin.Context) (data map[string]interface{}, err error) {
	// check params
	file, err := os.Open(conf.DirPath + "/files/template/用户导入模板.xlsx")
	if err != nil {
		return
	}
	value, err := ioutil.ReadAll(file)
	if err != nil {
		return
	}

	c.Writer.WriteHeader(http.StatusOK)
	c.Header("Content-Type", "application/octet-stream;charset=UTF-8")
	c.Header("Content-Disposition", "attachment; filename=用户导入模板.xlsx")
	c.Header("Accept-Length", fmt.Sprintf("%d", len(value)))
	c.Writer.Write(value)
	c.Abort()
	return
}
